package com.liuyjy.aop.encryptDecrypt;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.liuyjy.base.common.util.AESUtil;
import com.liuyjy.base.common.util.EmptyUtil;
import com.liuyjy.base.common.util.ObjConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author liuyjy
 * @Date 2025/2/21 12:18
 * @Description: 加解密处理器
 **/
@Slf4j
@Component
public class CryptoProcessor {
    private static final Map<Class<?>, List<Field>> FIELD_CACHE = new ConcurrentHashMap<>();


    /**
     * 核心处理方法（新增类型感知）
     * @param obj 对象
     * @param javaType 数据类型
     * @param encrypt 是否是加密
     * @param encryptType 本次处理类型是解密还是加密
     * @param enableALL 为否时只针对对象内部的值加密，例如 List<Long> 集合内部的值组个加密
     * @return Object
     */
    public Object processObject(Object obj, ResolvableType javaType, Boolean encrypt,boolean encryptType,boolean enableALL){
        if (obj == null) return null;

        if(null !=encrypt && encrypt && enableALL){
            //全字段加密时直接加密返回
            return encrypt(obj.toString());
        }
        Class<?> targetClass = javaType.resolve();
        if (targetClass == null) targetClass = Object.class;

        // 处理基本类型
        if (isPrimitiveOrWrapper(targetClass)) {
            return encryptDecrypt(obj, javaType, encrypt);
        }

        // 处理数组
        if (targetClass.isArray()) {
            return processArray(obj, javaType, encrypt,encryptType,enableALL);
        }

        // 处理集合
        if (Collection.class.isAssignableFrom(targetClass)) {
            return processCollection(obj, javaType, encrypt,encryptType,enableALL);
        }

        // 处理Map
        if (Map.class.isAssignableFrom(targetClass)) {
            return processMap(obj, javaType, encrypt,encryptType,enableALL);
        }

        // 处理自定义对象
        return processCustomObject(obj, javaType,encryptType);
    }

    /**
     * 处理数组（增强类型感知）
     * @param array 目标数组
     * @param javaType 类型
     * @param encrypt 加解密
     * @param encryptType 本次处理类型是解密还是加密
     * @param enableALL 为否时只针对对象内部的值加密，例如 List<Long> 集合内部的值组个加密
     * @return Object
     */
    private Object processArray(Object array,ResolvableType javaType, Boolean encrypt,boolean encryptType,boolean enableALL){
        ResolvableType componentType = javaType.getComponentType();
        int length = Array.getLength(array);
        for (int i = 0; i < length; i++) {
            Object element = Array.get(array, i);
            Object processed = processObject(element, componentType, encrypt,encryptType,enableALL);
            Array.set(array, i, processed);
        }
        return array;
    }

    /**
     * 处理集合（支持泛型）
     * @param collection 目标集合
     * @param javaType 类型
     * @param encrypt 加解密
     * @param encryptType 本次处理类型是解密还是加密
     * @param enableALL 为否时只针对对象内部的值加密，例如 List<Long> 集合内部的值组个加密
     * @return Object
     */
    private Object processCollection(Object collection,ResolvableType javaType, Boolean encrypt,boolean encryptType,boolean enableALL){
        if (!(collection instanceof Collection)) return collection;

        Collection<?> coll = (Collection<?>) collection;
        ResolvableType elementType = javaType.getGeneric(0);
        List<Object> result = new ArrayList<>(coll.size());

        for (Object element : coll) {
            result.add(processObject(element, elementType, encrypt,encryptType,enableALL));
        }
        return result;
    }


    /**
     * 处理Map（支持泛型）
     * @param mapObj 目标Map
     * @param javaType 类型
     * @param encrypt 加解密
     * @param encryptType 本次处理类型是解密还是加密
     * @param enableALL 为否时只针对对象内部的值加密，例如 List<Long> 集合内部的值组个加密
     * @return Object
     */
    private Object processMap(Object mapObj,ResolvableType javaType, Boolean encrypt,boolean encryptType,boolean enableALL){
        if (!(mapObj instanceof Map)) return mapObj;

        Map<?, ?> map = (Map<?, ?>) mapObj;
        //ResolvableType keyType = javaType.getGeneric(0);
        ResolvableType valueType = javaType.getGeneric(1);
        Map<Object, Object> result = new HashMap<>();

        for (Map.Entry<?, ?> entry : map.entrySet()) {
            //Object key = processObject(entry.getKey(), keyType, encrypt);
            //key不涉及加解密
            Object key = entry.getKey();
            Object value = processObject(entry.getValue(), valueType, encrypt,encryptType,enableALL);
            result.put(key, value);
        }
        return result;
    }

    /**
     * 处理自定义对象（增强字段类型处理）
     * @param obj 目标对象
     * @param javaType 对象类型
     * @param encryptType 本次处理类型是解密还是加密
     * @return Object
     */
    private Object processCustomObject(Object obj,ResolvableType javaType,boolean encryptType){
        if (obj == null) {
            return null;
        }
        Class<?> clazz = obj.getClass();
        List<Field> fields = getCachedFields(clazz);
        boolean enableALL =false;
        for (Field field : fields) {
            field.setAccessible(true);
            Boolean encryptFlag=null;

            if(encryptType && field.isAnnotationPresent(Encrypt.class)){
                Encrypt encrypt = field.getAnnotation(Encrypt.class);
                enableALL = encrypt.enableALL();

                encryptFlag=true;
            }else if(!encryptType && field.isAnnotationPresent(Decrypt.class)) {
                encryptFlag=false;
            }
//            boolean shouldProcess = encrypt ?
//                    field.isAnnotationPresent(Encrypt.class) :
//                    field.isAnnotationPresent(Decrypt.class);
            ResolvableType fieldType = ResolvableType.forField(field, javaType);

            if(null==encryptFlag && isPrimitiveOrWrapper(Objects.requireNonNull(fieldType.resolve()))){
                // 如果是基本类型 并且 不需要加密时，则跳过
                continue;
            }

            Object value = null;
            try {
                value = field.get(obj);
                Object processed = processObject(value, fieldType, encryptFlag,encryptType,enableALL);
                field.set(obj, processed);
            } catch (IllegalAccessException e) {
                log.error("Failed to process field: {}", field.getName(), e);
                throw new RuntimeException(e);
            }
        }
        return obj;
    }

    // 其他辅助方法保持不变

    /**
     * 获取字段缓存
     * @param clazz 目标类
     * @return List<Field>
     */
    private List<Field> getCachedFields(Class<?> clazz) {
        return FIELD_CACHE.computeIfAbsent(clazz, k -> {
            List<Field> fieldList = new ArrayList<>();
            Class<?> current = clazz;
            while (current != Object.class) {
                fieldList.addAll(Arrays.asList(current.getDeclaredFields()));
                current = current.getSuperclass();
            }
            return fieldList;
        });
    }

    /**
     * 是否为基本类型或包装类型
     * @param type 类型
     * @return boolean
     */
    private boolean isPrimitiveOrWrapper(Class<?> type) {
        return type.isPrimitive() ||
                type == String.class ||
                Number.class.isAssignableFrom(type) ||
                type == Integer.class ||
                type == Long.class ||
                type == Double.class ||
                type == Float.class ||
                type == Boolean.class ||
                type == Character.class ||
                type == Byte.class ||
                type == Short.class ||
                isDateType(type)
                ;
    }

    /**
     * 是否为日期类型
     * @param type 类型
     * @return boolean
     */
    private boolean isDateType(Class<?> type) {
        return Date.class.isAssignableFrom(type) ||
                java.time.temporal.Temporal.class.isAssignableFrom(type);
    }

    // 示例加密方法（需替换为实际算法）
    public String encrypt(String data) {
        return AESUtil.encrypt(data);
    }

    public String decrypt(String data) {
        return AESUtil.decrypt(data);
    }

    /**
     * 加解密处理
     * @param value 待处理值
     * @param javaType 对象类型
     * @param encrypt 加密或解密
     * @return Object
     */
    private Object encryptDecrypt(Object value,ResolvableType javaType, Boolean encrypt) {
        if(null==encrypt){
            return value;
        }
        if (encrypt) {
            return encrypt(value.toString());
        } else {
            if (value instanceof String) {
                String decrypted = decrypt((String) value);
                // 类型转换逻辑...
                return ObjConvertUtil.convert(decrypted, getReturnTypeAsJavaType(javaType));
            }
            return value;
        }
    }

    /**
     * 将 Method 的返回类型转换为 JavaType
     *
     * @param resolvableType 需要转换的  对象
     * @return 转换后的 JavaType 对象
     */
    public static JavaType getReturnTypeAsJavaType(ResolvableType resolvableType) {
        return TypeFactory.defaultInstance().constructType(resolvableType.getType());
    }

    public static void main(String[] args) {
        System.out.println(ObjConvertUtil.convert(1,Integer.class));
        System.out.println( ObjConvertUtil.convert("13213",String.class));
        System.out.println(ObjConvertUtil.convert(1,Integer.class));
        System.out.println( ObjConvertUtil.convert("可以了解更多我的能力",String.class));
    }
}

